[BATCH] 커서 방식의 주의점
NOTE
Spring Batch: Cursor vs Paging Reader 방식 비교 정리
📌 개념
- Spring Batch ItemReader 방식(Cursor / Paging) 비교
1. 커서(Cursor) 방식
- 핵심 개념: DB와 커넥션을 맺고 ResultSet을 오픈한 상태에서 데이터를 한 건씩 스트림(Stream) 형태로 읽어오는 방식
- 동작 원리
- 최초 1회 SELECT 쿼리 실행
- DB 서버에서 데이터를 조금씩 계속 끌어옴(Streaming)
- 장점
- 쿼리를 한 번만 날리므로 전체 조회 성능이 상대적으로 우수함
- 데이터 정합성이 보장됨(조회 시점의 스냅샷 기준)
- 단점 및 주의사항
- 커넥션 유지: 배치가 끝날 때까지 DB 커넥션을 점유함
- 타임아웃 위험: 로직이 무거워지면 Socket Timeout이나 Connection Timeout이 발생할 가능성이 매우 높음
2. 페이징(Paging) 방식
- 핵심 개념: 데이터를 특정 페이지 단위(Offset/Limit)로 끊어서 여러 번의 쿼리로 나누어 읽어오는 방식
- 동작 원리
- Chunk Size와 동일한 크기로 페이지를 나누어 쿼리 실행
- 매 페이지를 읽을 때마다 커넥션을 맺고 끊기를 반복
- 장점
- 한 번의 커넥션 유지 시간이 짧아 타임아웃 설정에 매우 안정적임
- 대량의 데이터를 처리할 때 가장 보편적으로 사용되는 방식
- 단점 및 주의사항
- 데이터 정합성 문제: 페이지를 읽는 사이에 데이터가 추가/삭제되면 중복 조회되거나 누락될 수 있음(정렬 조건 필수)
- 뒤로 갈수록 성능 저하: Offset 값이 커질수록 DB 스캔 비용이 증가함
핵심 요약 및 선택 가이드
| 비교 항목 | 커서 (Cursor) | 페이징 (Paging) |
|---|---|---|
| 커넥션 유지 | 배치 종료 시까지 (길음) | 페이지 조회 시만 (짧음) |
| 타임아웃 위험 | 높음 | 낮음 (안정적) |
| 데이터 정합성 | 우수 (Snapshot) | 조건에 따라 누락/중복 가능 |
| 추천 상황 | 정합성이 중요하고 로직이 가벼울 때 | 로직이 무겁거나 안정성이 최우선일 때 |
📌 비고
배치 로직의 복잡도가 높아질 가능성을 감안하면, 커넥션 이슈에서 자유로운 페이징 방식을 기본값으로 선택하는 경우가 많다.
다만 삭제 배치처럼 “읽으면서 삭제”하는 경우엔 페이징이 오히려 위험하다(Offset Shift로 인한 SKIP 누락).
관련 문서
- (Quartz) 대용량 계층적 삭제 배치 설계 패턴 - 핵심 개념 및 특징 정리 — “읽으면서 삭제”하는 배치에서 Cursor가 필수인 이유를 실제 삭제 배치 설계에 적용한 사례
- (Spring Batch) 대용량 데이터 대사·정산 배치 아키텍처와 장애 복구 패턴 — 동일한 Cursor vs Paging 선택 기준을 대사·정산 배치의 Reader 설계에 적용한 사례